package part21线程.线程通讯;

/**
 * 框：存储馒头 一个放馒头的方法(生产者调用)
 * 
 * 一个取馒头的方法(消费者调用)
 * 
 * @author Administrator
 *
 */
public class 框 {

	// 数组存放馒头，只有6个长度
	馒头[] ms = new 馒头[6];
	// 数组的下标，也可以表示馒头的数量
	int index = 0;

	/**
	 * 放馒头的方法 该方法为同步方法，持有方法锁
	 * 同一个时间内只能有一个生产者线程调用该方法;
	 * 循环判断框是否满的,如果是满的使线程进入等待状态.
	 * 当框有馒头,通知消费者来消费.
	 */
	public synchronized void push(馒头 mt) {
		// 共享空间 满时生产者不能继续生产 生产前循环判断是否为满，满的话将该线程wait
		while (index == ms.length) {
			System.out.println("----框已经满了，不能再生产，等消费者消费----");
			// 线程等待
			try {
				this.wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

		}
		// 框没有满，可以丢馒头到框里面
		ms[index] = mt;
		// 馒头数量+1
		index++;
		// 通知:通知等待的消费者线程可以消费
//		this.notify();
		this.notifyAll();

	}

	/**
	 * 取馒头的方法
	 * 同一个时间内只能有一个消费者线程调用该方法
	 * 循环判断框是否空的,如果是空的使线程进入等待状态.
	 * 框不是空的,可以取馒头,就也要通知生产者要生产.
	 */
	public synchronized 馒头 pop() {
		// 共享空间 空 时消费者不能继续消费 消费前循环判断是否为空，空的话将该线程wait
		while (index == 0) {

			System.out.println("~~~~框已经空了，不能再消费，等生产者生产~~~~");
			// 线程等待
			try {
				this.wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
		// 框有馒头,可以消费
		// 馒头数量-1
		index--;
		// 通知:等待的生产者线程可以继续生产
//		this.notify();
		this.notifyAll();
		return ms[index];
	}
}
